import axios from 'axios'
import {
    ElNotification,
    ElMessageBox,
    ElLoading,
    ElMessage
} from 'element-plus'
import {getToken} from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import {tansParams, blobValidate} from '@/utils/commonFunction'
import cache from '@/plugins/cache'
import {saveAs} from 'file-saver'
import {showScreenLoading, hideScreenLoading} from './loading'
import {logoutSystem} from './user'

let downloadLoadingInstance: any
// 是否显示重新登录
export let isRelogin = {show: false}

// axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
    // axios中请求配置有baseURL选项，表示请求URL公共部分
    baseURL: import.meta.env.VITE_APP_API_PREFIX,

    // 超时
    timeout: 120000
})
const notShowLoadUrls = ['/login', '/getInfo', '/getRouters']
// request拦截器
service.interceptors.request.use(
    (config: any) => {

        if (showLoading(config.url)) {
            showScreenLoading(config.headers)
        }
        // 是否需要设置 token
        const isToken = (config.headers || {}).isToken === false
        // 是否需要防止数据重复提交
        const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
        if (getToken() && !isToken) {
            config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
        }
        // get请求映射params参数
        if (config.method === 'get' && config.params) {
            let url = config.url + '?' + tansParams(config.params)
            url = url.slice(0, -1)
            config.params = {}
            config.url = url
        }
        if (
            !isRepeatSubmit &&
            (config.method === 'post' || config.method === 'put')
        ) {
            const requestObj = {
                url: config.url,
                data:
                    typeof config.data === 'object'
                        ? JSON.stringify(config.data)
                        : config.data,
                time: new Date().getTime()
            }
            const requestSize = Object.keys(JSON.stringify(requestObj)).length // 请求数据大小
            const limitSize = 5 * 1024 * 1024 // 限制存放数据5M
            if (requestSize >= limitSize) {
                console.warn(
                    `[${config.url}]: ` +
                    '请求数据大小超出允许的5M限制，无法进行防重复提交验证。'
                )
                return config
            }
            const sessionObj = cache.session.getJSON('sessionObj')
            if (
                sessionObj === undefined ||
                sessionObj === null ||
                sessionObj === ''
            ) {
                cache.session.setJSON('sessionObj', requestObj)
            } else {
                const s_url = sessionObj.url // 请求地址
                const s_data = sessionObj.data // 请求数据
                const s_time = sessionObj.time // 请求时间
                const interval = 1000 // 间隔时间(ms)，小于此时间视为重复提交
                if (
                    s_data === requestObj.data &&
                    requestObj.time - s_time < interval &&
                    s_url === requestObj.url
                ) {
                    const message = '数据正在处理，请勿重复提交'
                    console.warn(`[${s_url}]: ` + message)
                    return Promise.reject(new Error(message))
                } else {
                    cache.session.setJSON('sessionObj', requestObj)
                }
            }
        }
        return config
    },
    error => {
        console.log(error)
        Promise.reject(error)
    }
)

// 响应拦截器
service.interceptors.response.use(
    res => {
        hideScreenLoading()
        // 未设置状态码则默认成功状态
        const code = res.data.status || 0
        // 获取错误信息
        const msg = errorCode[code] || res.data.msg || errorCode['default']
        // 二进制数据则直接返回
        if (
            res.request.responseType === 'blob' ||
            res.request.responseType === 'arraybuffer'
        ) {
            return res.data
        }

        if (code == 401) {
            authenticationFailedAndReLogin()
        } else if (code == 500) {
            if (msg.indexOf('登陆失败') > -1) {
                ElMessage({ message: msg, type: 'error' })
                return Promise.reject(new Error(msg))
            }
            if (msg.indexOf('认证失败') > -1 || !getToken()) {
                authenticationFailedAndReLogin()
            } else {
                // ElMessage({ message: msg, type: 'error' })
                return Promise.reject(new Error(msg))
            }
        } else if (code == 601) {
            // ElMessage({ message: msg, type: 'warning' })
            return Promise.reject('error')
        } else if (code != 0) {
            // ElNotification.error({ title: msg })
            return Promise.reject('error')
        } else {
            // 响应数据
            return res.data
        }
    },
    error => {
        hideScreenLoading()
        console.log('err' + error)
        let {message} = error
        if (message == 'Network Error') {
            message = '后端接口连接异常'
        } else if (message.includes('timeout')) {
            message = '系统接口请求超时'
        } else if (message.includes('Request failed with status code')) {
            message = '系统接口' + message.substr(message.length - 3) + '异常'
        }
        // ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
        return Promise.reject(error)
    }
)

// 通用下载方法
export function download(
    url: string,
    params: any,
    filename: string,
    config: any
) {
    downloadLoadingInstance = ElLoading.service({
        text: '正在下载数据，请稍候',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
    })
    return service
        .post(url, params, {
            transformRequest: [
                params => {
                    return tansParams(params)
                }
            ],
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            responseType: 'blob',
            ...config
        })
        .then(async (data: any) => {
            const isBlob = blobValidate(data)
            if (isBlob) {
                const blob = new Blob([data])
                saveAs(blob, filename)
            } else {
                const resText = await data.text()
                const rspObj = JSON.parse(resText)
                const errMsg =
                    errorCode[rspObj.code] || rspObj.msg || errorCode['default']
                ElMessage.error(errMsg)
            }
            downloadLoadingInstance.close()
        })
        .catch(r => {
            console.error(r)
            ElMessage.error('下载文件出现错误，请联系管理员！')
            downloadLoadingInstance.close()
        })
}

// 下载并返回文件对象
export function downloadAndReturn(
    url: string,
    params: any,
    filename: string,
    config: any
) {
    downloadLoadingInstance = ElLoading.service({
        text: '正在下载数据，请稍候',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
    })
    return service
        .post(url, params, {
            transformRequest: [
                params => {
                    return tansParams(params)
                }
            ],
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            responseType: 'blob',
            ...config
        })
        .then(async (data: any) => {
            const isBlob = blobValidate(data)
            if (isBlob) {
                const blob = new Blob([data])
                return {
                    file: blob,
                    fileName: filename
                }
            } else {
                const resText = await data.text()
                const rspObj = JSON.parse(resText)
                const errMsg =
                    errorCode[rspObj.code] || rspObj.msg || errorCode['default']
                ElMessage.error(errMsg)
            }
            downloadLoadingInstance.close()
        })
        .catch(r => {
            console.error(r)
            ElMessage.error('下载文件出现错误，请联系管理员！')
            downloadLoadingInstance.close()
        })
}

//认证失败
function authenticationFailedAndReLogin() {
    if (!isRelogin.show) {
        isRelogin.show = true
        ElMessageBox.confirm(
            '登录状态已过期，您可以继续留在该页面，或者重新登录',
            '系统提示',
            {
                confirmButtonText: '重新登录',
                cancelButtonText: '取消',
                type: 'warning'
            }
        )
            .then(async () => {
                isRelogin.show = false
                logoutSystem()
            })
            .catch(() => {
                isRelogin.show = false
            })
    }
    return Promise.reject('无效的会话，或者会话已过期，请重新登录。')
}

// 上传文件
export function uploadFileRequest(
    url: string,
    file: File,
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
) {
    // 创建一个FormData对象
    let formData = new FormData()
    // 添加文件
    formData.append('file', file)
    // 发送POST请求
    downloadLoadingInstance = ElLoading.service({
        text: '正在上传，请稍候',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
    })
    return service
        .post(url, formData, {
            headers: headers
        })
        .catch(err => {
            ElMessage.error('上传出现错误')
        })
        .finally(() => {
            downloadLoadingInstance.close()
        })
}

const showLoading = function (curl: string) {
    let f = true
    for (let i = 0; i < notShowLoadUrls.length; i++) {
        if (curl.indexOf(notShowLoadUrls[i]) != -1) {
            f = false
            break
        }
    }
    return f
}
export default service
